/****************************************************************************
*                                                                           *
* scatblock.h									                            *
*                                                                           *
* ALaRI 2008												                *
*                                                                           *
****************************************************************************/
#pragma once

#if !defined(__SCATBLOCK_H)
#define __SCATBLOCK_H

/****************************************************************************
* Includes										                            *
****************************************************************************/
#include <complex>
#include "../../common/defs.h"

/****************************************************************************
* Forward declarations							                            *
****************************************************************************/
class CScatBlockLPT;
class CTransform;

/****************************************************************************
* CTransform - helpers for transformations		                            *
****************************************************************************/
class CTransform
{
public:

	//	!!!NOTE: don't change numbers of enum - we have logic based on it
	enum eTransform
	{
		eTransform_r0	= 0,
		eTransform_r90	= 1,
		eTransform_r180	= 2,
		eTransform_r270	= 3,
		// flip-x and rotate
		eTransform_fr0	= 4,
		eTransform_fr90	= 5,
		eTransform_fr180= 6,
		eTransform_fr270= 7,
		// number of transforms
		eTransform_count= 8
	};

	/****************************************************************************
	* General helpers															*
	****************************************************************************/
	static eTransform combineTransforms(eTransform nTransform1, eTransform nTransform2);
};

/****************************************************************************
* CScatBlock - scattering matrix block										*
****************************************************************************/
class CScatBlock
{
public:

	/****************************************************************************
	* Overrides																	*
	****************************************************************************/
	// width and height of the block
	virtual int getWidth() const = 0;
	virtual int getHeight() const = 0;
	// get transformed scattering block
	virtual const CScatBlock* getTransformed(
		CTransform::eTransform nTransform, bool bCreateIfNotThere) const = 0;
	// get value at row, column
	virtual std::complex<float>& valueAt(int nRow, int nColumn) = 0;

	/****************************************************************************
	* Destruction																*
	****************************************************************************/
	virtual ~CScatBlock() {}

	/****************************************************************************
	* Public Access																*
	****************************************************************************/
	const std::complex<float>& valueAt(int nRow, int nColumn) const
		{ return ((CScatBlock*)this)->valueAt(nRow, nColumn); }
};

/****************************************************************************
* CScatBlockL0 - private class for scattering matrix (level 0)				*
****************************************************************************/
class CScatBlockL0 : public CScatBlock
{
public:

	/****************************************************************************
	* Construction																*
	****************************************************************************/
	CScatBlockL0(const std::complex<float>& fltThetta);

	/****************************************************************************
	* Overrides																	*
	****************************************************************************/
	virtual int getWidth() const;
	virtual int getHeight() const;
	virtual const CScatBlock* getTransformed(
		CTransform::eTransform nTransform, bool bCreateIfNotThere) const;
	virtual std::complex<float>& valueAt(int nRow, int nColumn);

protected:

	/****************************************************************************
	* Protected data															*
	****************************************************************************/
	std::complex<float>	m_fltThetta;
};

/****************************************************************************
* CScatBlockLP - scat matrix block data for LP matrices						*
****************************************************************************/
class CScatBlockLP : public CScatBlock
{
public:

	/****************************************************************************
	* Overrides																	*
	****************************************************************************/
	virtual int getWidth() const;
	virtual int getHeight() const;
	virtual const CScatBlock* getTransformed(
		CTransform::eTransform nTransform, bool bCreateIfNotThere) const;
	virtual std::complex<float>& valueAt(int nRow, int nColumn);

	/****************************************************************************
	* Construction																*
	****************************************************************************/
	CScatBlockLP(bool bSymetric, int nWidth, int nHeight);
	~CScatBlockLP();

	/****************************************************************************
	* Public access																*
	****************************************************************************/
	void invert();

protected:

	/****************************************************************************
	* Protected helpers															*
	****************************************************************************/
	static std::complex<float>** allocData(int nWidth, int nHeight, bool bSymetric);
	static void freeData(std::complex<float>** pData, int nHeight, bool bSymetric);

	/****************************************************************************
	* Protected data															*
	****************************************************************************/
	// transformations owned by this block
	CScatBlockLPT*		m_rgnpTransforms[CTransform::eTransform_count - 1];
	// the block is symetric
	bool				m_bSymetric;
	// size of the block
	int					m_nWidth;
	int					m_nHeight;
	// pointer to array of rows
	std::complex<float>	**m_ppfltData;
};

/****************************************************************************
* CScatBlockLPT - scat matrix block transform for LP matrices				*
****************************************************************************/
class CScatBlockLPT : public CScatBlock
{
public:

	/****************************************************************************
	* Overrides																	*
	****************************************************************************/
	virtual int getWidth() const;
	virtual int getHeight() const;
	virtual const CScatBlock* getTransformed(
		CTransform::eTransform nTransform, bool bCreateIfNotThere) const;
	virtual std::complex<float>& valueAt(int nRow, int nColumn);

private:

	/****************************************************************************
	* Construction																*
	****************************************************************************/
	CScatBlockLPT(CScatBlockLP* pOwner, CTransform::eTransform nTransform);

	/****************************************************************************
	* Created and managed by CScatBlockLP										*
	****************************************************************************/
	friend class CScatBlockLP;

	/****************************************************************************
	* Protected data															*
	****************************************************************************/
	CScatBlockLP			*m_pOwner;
	CTransform::eTransform	m_nTransform;
};

#endif /* __SCATBLOCK_H */

/****************************************************************************
* End of file																*
****************************************************************************/
